<!--
 * @Author: Xujianchen
 * @Date: 2024-12-24 08:56:56
 * @LastEditors: Xujianchen
 * @LastEditTime: 2025-01-18 16:09:23
 * @Description: better-scroll吸顶、下拉效果展示
-->
<template>
  <Wrapper>
    <el-card header="吸顶、下拉效果展示" shadow="never">
      <div ref="containerRef" class="result-container">
        <div class="result-header">
          <icon class="icon" name="ArrowLeft" />
          <h4>{{ title }}</h4>
        </div>
        <div
          ref="bgImageRef"
          class="result-header-bg-image"
          :style="bgImageStyle"
        >
          <div class="result-header-filter" :style="filterStyle"></div>
        </div>
        <scroll
          :probe-type="3"
          :style="scrollStyle"
          class="result-list-container"
          @scroll="handleScroll"
        >
          <div class="result-list-wrapper">
            <div
              v-for="(item, index) in menuList"
              :key="item.path"
              :data-index="index"
              class="result-list-item"
            >
              <span class="result-list-item-index">{{ index + 1 }}、</span>
              <icon
                v-if="item.meta.icon"
                :name="item.meta.icon"
                :type="item.meta.iconType"
                class="result-list-item-icon"
              />
              <div class="result-list-item-title">{{ item.meta.title }}</div>
            </div>
          </div>
        </scroll>
      </div>
    </el-card>
  </Wrapper>
</template>

<script setup>
import { cssVars } from '@/const'
import useAuthStore from '@/store/modules/auth'
import bgImageURL from '@/assets/images/Director-General-Progress-Text.png'
import Scroll from '../components/scroll'

const menuList = computed(() => useAuthStore().menuList)

const bgImageRef = ref(null)
const containerRef = ref(null)
const title = ref('老师，我太想进步了')
const list = ref([])
const state = ref({
  imgHeight: 0,
  scrollY: 0,
  maxTranslateY: 0,
})
const HEIGHT = 40
let observer

onMounted(() => {
  state.value.imgHeight = bgImageRef.value.clientHeight || 265
  state.value.maxTranslateY = state.value.imgHeight - HEIGHT
})

onBeforeUnmount(() => {
  if (observer) {
    observer.disconnect()
  }
})

const bgImageStyle = computed(() => {
  const value = state.value
  let zIndex = 0
  let height = 0
  let scale = 1
  let paddingTop = '70%'
  // FIXME: 定义translateZ兼容ios不覆盖的问题
  let translateZ = 0

  if (value.scrollY > value.maxTranslateY) {
    zIndex = 10
    paddingTop = 0
    height = `${HEIGHT}px`
    translateZ = 1
  }
  if (value.scrollY < 0) {
    // 由于scrollY < 0
    scale = 1 + Math.abs(value.scrollY / value.imgHeight)
  }
  return {
    zIndex,
    height,
    paddingTop,
    backgroundImage: `url(${bgImageURL})`,
    transform: `scale(${scale})translateZ(${translateZ}px)`,
    transition: 'padding-top .3s',
  }
})
const filterStyle = computed(() => {
  let blur = 0
  const value = state.value
  // scrollY大于0则代表向上推
  if (value.scrollY >= 0) {
    blur =
      Math.min(
        value.maxTranslateY / value.imgHeight,
        value.scrollY / value.imgHeight,
      ) * 20
  }
  return {
    backdropFilter: `blur(${blur}px)`,
  }
})
const scrollStyle = computed(() => {
  const bottom = list.value.length ? cssVars.spaceMedium : 0
  return {
    top: `${state.value.imgHeight}px`,
    bottom,
  }
})

// scroll组件派发事件
function handleScroll(pos) {
  state.value.scrollY = -pos.y
  const value = state.value
  const items = document.querySelectorAll('.result-list-item')
  let closestItem = null
  let minDistance = Infinity
  // 计算每个列表项与result-container的距离
  items.forEach((item) => {
    const rect = item.getBoundingClientRect()
    const containerRect = containerRef.value.getBoundingClientRect()
    const distance = Math.abs(rect.top - (containerRect.top + HEIGHT))

    if (distance < minDistance) {
      minDistance = distance
      closestItem = item
    }
  })
  if (closestItem && value.scrollY > value.imgHeight - HEIGHT) {
    title.value = list.value[+closestItem.dataset.index].meta.title
  }
  if (value.scrollY < 1) {
    title.value = '老师，我太想进步了'
  }
}
</script>

<style scoped lang="scss">
.result {
  &-container {
    position: relative;
    overflow: hidden;
    width: 355px;
    height: 580px;
    border: 1px solid var(--el-card-border-color);
    background-color: $app-bg-color;
  }

  // 头部区域
  &-header {
    position: absolute;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: calc(100% - $space-small-s * 3);
    height: 40px;
    line-height: 40px;
    color: var(--el-color-white);

    .icon {
      flex: 0;
      margin-left: $space-small-s;
    }

    h4 {
      flex: 1;
      text-align: center;
    }
  }

  &-header-bg-image {
    position: relative;
    width: 100%;
    transform-origin: top;
    background-size: cover;
    background-position: -50px center;
  }

  &-header-filter {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(7, 17, 27, 0.4);
  }

  // 列表
  &-list-container {
    position: absolute;
    bottom: 0;
    z-index: 0;
    width: 100%;
  }

  &-list-wrapper {
    padding: $space-medium-s $space-large;
    padding-top: 0;
  }

  &-list-item {
    display: flex;
    align-items: center;
    box-sizing: border-box;
    height: 32px;
    font-size: $font-size-medium;
  }

  &-list-item-index {
    width: 40px;
  }

  &-list-item-icon {
    margin-right: $space-small-s;
  }

  &-list-item-title {
    width: 300px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
</style>
